using System.Collections;
using System.Collections.Generic;
//TODO: Check that the count of rows in a column matches the count of rows in the column set when a column is added
namespace OllieExplorer
{
    public class GridColumns : IList<GridColumn>
    {
        private readonly IList<GridColumn> _Columns = new List<GridColumn>();
        internal delegate void ColumnChangedDelegate(GridColumns gridCoulmns, int index);
        internal delegate void ColumnDelegate(GridColumns gridColumns);
        private ColumnChangedDelegate _ColumnRemoved;
        private ColumnChangedDelegate _ColumnChanged;
        private ColumnChangedDelegate _ColumnAdded;
        private ColumnDelegate _ColumnCleared;
        

        internal ColumnChangedDelegate ColumnChanged
        {
            get
            {
                return _ColumnChanged;
            }
            set
            {
                _ColumnChanged = value;
            }
        }

        internal ColumnChangedDelegate ColumnRemoved
        {
            get
            {
                return _ColumnRemoved;
            }
            set
            {
                _ColumnRemoved = value;
            }
        }

        internal ColumnChangedDelegate ColumnAdded
        {
            get
            {
                return _ColumnAdded;
            }
            set
            {
                _ColumnAdded = value;
            }
        }

        internal ColumnDelegate ColumnCleared
        {
            get
            {
                return _ColumnCleared;
            }
            set
            {
                _ColumnCleared = value;
            }
        }

        private void ColumnRezied(GridColumn gridColumn)
        {
            RepackColumns(_Columns.IndexOf(gridColumn));
        }

        internal void RepackColumns(int startIndex)
        {
            int startX;
            if (startIndex > 0)
            {
                startX = _Columns[startIndex - 1].End + 1;
            }
            else
            {
                startX = 0;
            }
            if (startIndex < _Columns.Count)
            {
                for (int counter = startIndex; counter < _Columns.Count; counter++)
                {
                    _Columns[counter].Start = startX;
                    _Columns[counter].End = _Columns[counter].Start + _Columns[counter].Width - 1;
                    startX += _Columns[counter].Width;
                }
            }
        }

        IEnumerator<GridColumn> IEnumerable<GridColumn>.GetEnumerator()
        {
            return _Columns.GetEnumerator();
        }

        public bool Remove(GridColumn item)
        {
            int index = item.Id;
            bool result = _Columns.Remove(item);
            RepackColumns(index);
            if (_ColumnRemoved != null)
            {
                _ColumnRemoved(this, index);
            }
            return result;
        }

        public int Count
        {
            get { return _Columns.Count; }
        }

        public void Add(GridColumn item)
        {
            item.Id = _Columns.Count;
            _Columns.Add(item);            
            RepackColumns(_Columns.Count - 1);
            item.Resized += ColumnRezied;
            if (_ColumnAdded != null)
            {
                _ColumnAdded(this, item.Id);
            }
        }

        public void Clear()
        {
            _Columns.Clear();
            if (_ColumnCleared != null)
            {
                _ColumnCleared(this);
            }
        }

        public bool Contains(GridColumn item)
        {
            return _Columns.Contains(item);
        }

        public void CopyTo(GridColumn[] array, int arrayIndex)
        {
            _Columns.CopyTo(array, arrayIndex);
        }

        public int IndexOf(GridColumn item)
        {
            return _Columns.IndexOf(item);
        }

        public void Insert(int index, GridColumn item)
        {
            item.Id = index;
            for (int counter = index; counter < _Columns.Count; counter++ )
            {
                _Columns[counter].Id++;
            }
            _Columns.Insert(index, item);
            RepackColumns(index);
            item.Resized += ColumnRezied;
            if (_ColumnAdded != null)
            {
                _ColumnAdded(this, index);
            }
        }

        public void RemoveAt(int index)
        {
            for (int counter = index + 1; counter < _Columns.Count; counter++)
            {
                _Columns[counter].Id--;
            }
            _Columns.RemoveAt(index);
            RepackColumns(index);
            if (_ColumnRemoved != null)
            {
                _ColumnRemoved(this, index);
            }
        }

        internal GridColumn FindColumn(int x)
        {
            foreach (GridColumn column in _Columns)
            {
                if (x > column.End)
                {
                    continue;
                }
                return column;
            }
            return null;
        }

        public GridColumn this[int index]
        {
            get { return _Columns[index]; }
            set
            {
                _Columns[index] = value;
                value.Id = index;
                RepackColumns(index);
                value.Resized += ColumnRezied;
                if (_ColumnChanged != null)
                {
                    _ColumnChanged(this, index);
                }
            }
        }

        public bool IsReadOnly
        {
            get { return _Columns.IsReadOnly; }
        }

        public IEnumerator GetEnumerator()
        {
            return _Columns.GetEnumerator();
        }
    }

}
